package observer

import "fmt"

// Subject 目标对象，它知道观察它的观察者，饼干提供注册和删除观察者的接口
type Subject struct {
	// 用来保存注册的观察者对象
	observers []Observer
	// 示意，目标的状态
	subjectState string
}

// Attach 注册观察者对象
func (s *Subject) Attach(observer Observer) {
	s.observers = append(s.observers, observer)
}

// Detach 删除观察者对象
func (s *Subject) Detach(observer Observer) {
	var res []Observer
	for _, ob := range s.observers {
		if ob != observer {
			res = append(res, ob)
		}
	}
	s.observers = res
}

// notifyObservers 通知所有注册的观察者对象
func (s *Subject) notifyObservers() {
	for _, observer := range s.observers {
		observer.Update(s)
	}
}

func (s *Subject) SetSubjectState(state string) {
	s.subjectState = state
	// 状态发生了改变，通知各个观察者
	s.notifyObservers()
}

func (s *Subject) getSubjectState() string {
	return s.subjectState
}

// Observer 观察者接口，定义一个更新的接口给那些在目标发生改变的时候被通知的对象
type Observer interface {
	// Update 更新的接口
	// 传入一个目标对象，方便获取相应的目标对象的状态
	Update(subject *Subject)
}

// ConcreteObserver 具体观察者 对象，实现更新的方法，使自身的状态和目标的状态保持一致
type ConcreteObserver struct {
	// 示意，观察者的状态
	observerState string
}

func (c *ConcreteObserver) Update(subject *Subject) {
	// 具体的更新实现
	// 这里可能需要更新观察者的状态，使其与目标的状态保持一致
	fmt.Printf("Observer %s => Subject %s\n", c.observerState, subject.getSubjectState())
	//c.observerState = subject.getSubjectState()
	//subject.SetSubjectState("")
}
